#region License, Terms and Conditions
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;
using pesta.Data.Model.Helpers;
using raya.ActionFilters;
using raya.Models.activities;
using raya.Models.applications;
using raya.Models.login;
using raya.Models.notifications;
using raya.Models.people;
using raya.Models.photos;

namespace raya.Controllers
{
    //[HandleError(ExceptionType = typeof(FacebookException),View = "FacebookError")]
    //[HandleError]
    [CompressFilter]
    public class baseController : Controller
    {
        protected login theUser;

        public baseController()
        {
            theUser = new login();
        }
        protected void handleErrors(string errorMessage)
        {
            Session["message"] = errorMessage;

            // TODO: we need log this as well
        }

        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
            base.Initialize(requestContext);
            var user = theUser.GetLoggedIn();

            // allow logins anywhere in the site
            if (Session["id"] == null &&
                !String.IsNullOrEmpty(Request.Form["email"]) &&
                !String.IsNullOrEmpty(Request.Form["password"]))
            {
                if (Authenticate(Request.Form["email"], Request.Form["password"]))
                {
                    // Redirect to self, but without post to prevent posting if the user refreshes the page
                    // Login request to /openid/login page should not be redirected.
                    if (Request.ServerVariables["REQUEST_URI"] != null &&
                        Request.ServerVariables["REQUEST_URI"] != "/login/openid")
                    {
                        Redirect(Request.ServerVariables["REQUEST_URI"]);
                    }
                }
            }
            
            if (user != null)
            {
                user.SetSession(Session);
            }
        }

        protected bool Authenticate(string email, string password)
        {
            theUser = login.Authenticate(email, password);
            if (theUser != null)
            {
                // setup the session
                theUser.SetSession(Session);
                // and set a cookie and store the authenticated state in the authenticated table
                SHA1 sha = SHA1.Create();
                string hash = Encoding.ASCII.GetString(sha.ComputeHash(Encoding.ASCII.GetBytes(email + password)));
                //login.AddAuthenticated(theUser.id, hash);
                // remeber cookie for 30 days, after which we"d like the user to authenticate again
                if (Response.Cookies["authenticated"] != null)
                {
                    Response.Cookies["authenticated"].Value = HttpUtility.UrlEncode(hash);
                    Response.Cookies["authenticated"].Expires = DateTime.Now.AddMonths(1);
                }
                return true;
            }
            return false;
        }

        protected ActionResult RedirectToLogin()
        {
            return Redirect("/login?redirect=" + HttpUtility.UrlEncode(Request.Url.PathAndQuery));
        }

        
        
#if AZURE
#if DEBUG
        public Profile GetProfile(string pid)
#else
        protected Profile GetProfile(string pid)
#endif
        {
            return GetProfile(pid, 0, 0);
        }
        protected Profile GetProfile(string pid, int friendsStart, int friendsCount)
        {
            var people = new people();
            var apps = new applications();
            var notifys = new notifications();
            var activities = new activities();
            var photo = new photos();

            bool isFriend = false;
            bool isOwner = false;
            if (Session["id"] != null)
            {
                isOwner = Session["id"].ToString() == pid;
                isFriend = Session["id"].ToString() == pid ? false : people.IsFriend(pid, Session["id"].ToString());
            }

            var thisProfile = new Profile();
            thisProfile.person = people.GetPerson(pid, true);
            thisProfile.activities = activities.get_person_activities(pid, 10, thisProfile.person.loginInfo.name);
            thisProfile.applications = apps.get_person_applications(pid);
            thisProfile.friends = people.GetFriends(pid, friendsStart, friendsCount).ToList();
            thisProfile.is_friend = isFriend;
            thisProfile.is_owner = isOwner;
            thisProfile.photos = photo.getImages(pid);

            // only need to do the following for owners
            if (isOwner)
            {
                // facebook connect stuff
                if (theUser.IsConnectedToFacebook() &&
                    Session["fbuid"] != null &&
                    (long)Session["fbuid"] > 0)
                {
                    // get unconnected friends
                    thisProfile.unconnectedFBFriendsCount = theUser.fbclient.api.connect.getUnconnectedFriends();
                    // get connected friends
                    var connected = theUser.fbclient.api.friends.getAppUsersObjects();

                    thisProfile.newFriends = people.GetNewConnectedFBFriends(connected.Select(x => x.uid.Value).ToList(), pid);
                }

                var notificationCounts = new Dictionary<notifications.notifyType, int>();
                var notifyList = notifys.GetNotifications(pid);
                notificationCounts[notifications.notifyType.friendRequest] = notifyList.FindAll(x => x.type == notifications.notifyType.friendRequest.ToInt()).Count;
                //notificationCounts[notifications.notifyType.friendRecommend] = notifyList.FindAll(x => x.type == notifications.notifyType.friendRecommend).Count;
                notificationCounts[notifications.notifyType.friendRecommend] = thisProfile.newFriends != null ? thisProfile.newFriends.Count : 0;
                thisProfile.notifications = new ProfileNotification()
                {
                    notifyList = notifyList,
                    count = notificationCounts
                };
            }
            people.Dispose();
            activities.Dispose();
            apps.Dispose();
            notifys.Dispose();
            photo.Dispose();

            return thisProfile;
        }
#else
#if DEBUG
        public Profile GetProfile(string pid)
#else
        protected Profile GetProfile(string pid)
#endif
        {
            return GetProfile(pid, 0, 0);
        }

        protected Profile GetProfile(string id, int friendsStart, int friendsCount)
        {
            int pid = 0;
            if (!int.TryParse(id, out pid))
            {
                throw new Exception("invalid userid: " + id);
            }
            var people = new people();
            var apps = new applications();
            var notifys = new notifications();
            var activities = new activities();
            var photo = new photos();

            bool isFriend = false;
            bool isOwner = false;
            if (Session["id"] != null)
            {
                isOwner = Session["id"].ToString() == pid.ToString();
                isFriend = Session["id"].ToString() == pid.ToString() ? false : people.IsFriend(id, Session["id"].ToString());
            }

            var thisProfile = new Profile
            {
                activities = activities.get_person_activities(pid, 10),
                applications = apps.get_person_applications(pid),
                person = people.GetPerson(id, true),
                friends = people.GetFriends(id, friendsStart, friendsCount).ToList(),
                is_friend = isFriend,
                is_owner = isOwner,
                photos = photo.getImages(pid)
            };

            // only need to do the following for owners
            if (isOwner)
            {
                // facebook connect stuff
                if (theUser.IsConnectedToFacebook() &&
                    Session["fbuid"] != null &&
                    (long)Session["fbuid"] > 0)
                {
                    // get unconnected friends
                    thisProfile.unconnectedFBFriendsCount = theUser.fbclient.api.connect.getUnconnectedFriends();
                    // get connected friends
                    var connected = theUser.fbclient.api.friends.getAppUsersObjects();

                    thisProfile.newFriends = people.GetNewConnectedFBFriends(connected.Select(x => x.uid.Value).ToList(), pid);
                }

                var notificationCounts = new Dictionary<notifications.notifyType, int>();
                List<Notification> notifyList = notifys.GetNotifications(pid);
                notificationCounts[notifications.notifyType.friendRequest] = notifyList.FindAll(x => x.type == (int)notifications.notifyType.friendRequest).Count;
                //notificationCounts[notifications.notifyType.friendRecommend] = notifyList.FindAll(x => x.type == notifications.notifyType.friendRecommend).Count;
                notificationCounts[notifications.notifyType.friendRecommend] = thisProfile.newFriends != null ? thisProfile.newFriends.Count : 0;
                thisProfile.notifications = new ProfileNotification()
                {
                    notifyList = notifyList,
                    count = notificationCounts
                };
            }
            people.Dispose();
            activities.Dispose();
            apps.Dispose();
            notifys.Dispose();
            photo.Dispose();

            return thisProfile;
        }
#endif
        
    }
}